home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2006 November
/
PCWorld_2006-11_cd.bin
/
domacnost a kancelar
/
findgraph
/
fgraph.exe
/
{app}
/
ApprSource
/
poli_n.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2005-08-29
|
12KB
|
504 lines
/******************************************************************************
* Plug-In DLL Example and Template
* for use with C/C++
*
* Compile DLL with any name.
* Place it in the program FindGraph subfolder "Appr".
* Next functions must be exported:
* MaxOfFactors
* Prepare
* CalcInPoint
* FunctionTitle
* FunctionName
* FunctionString
* ParamInfo
*
* To test DLL, restart FundGraph,
* start The Wizard of approximation,
* on step 2 select 'User defined function'.
* If all right, on step 3 your function will appear in list.
*
******************************************************************************/
#include <windows.h>
#include <tchar.h>
#include <math.h>
#include "poli_n.h"
#include <stdio.h>
//
#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX /IGNORE:4078")
//////////////////////////////////////////////////////////////////////////////////
HINSTANCE g_hInstance=NULL;
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInstance = (HINSTANCE )hModule;
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#define N_FACTORS 18
#define aa(i,j) pfs[i*nn+j]
// calc f**n
double PowInt( double f, int n)
{
double val=1.;
if ( n ) for ( int i=1; i<=n; i++ )
val *= f;
return val;
}
// Calc line equations
// nAppr - number equations
// fs - coeffs. matrix aa(i,j)
// fu - buffer to return results
//
void CalcEquGauss(UINT nAppr, double *pfs, double *pfu)
{
int i, j, k,
n = nAppr,
nn = n+2;
for (i=0; i <= n; i++)
{
for (k=n+1; k >= i; k--)
aa(i,k) /= aa(i,i);
if (i < n)
for (j=i+1; j <= n; j++)
for (k=n+1; k >= 0; k--)
aa(j,k) -= (aa(j,i)*aa(i,k));
}
pfu[n] = aa(n,n+1);
if (n)
for (i=n-1; i >= 0; i-- )
for (k=i+1, pfu[i] = aa(i,n+1); k<= n; k++)
pfu[i] -= (aa(i,k)*pfu[k]);
}
// return number points with u != fNullU
//
int FindLimits(double &fMinU, double &fMaxU, double &fMinV, double &fMaxV,
double *pfU, double *pfV, int nPoints, double fNullU)
{
int np = 0;
for (int i=0; i<nPoints; i++)
{
double u = pfU[i],
v = pfV[i];
if (fNullU == u) continue;
if (np==0)
{
fMinU = fMaxU = u;
fMinV = fMaxV = v;
}
else
{
if (fMinU > u) fMinU = u;
if (fMaxU < u) fMaxU = u;
if (fMinV > v) fMinV = v;
if (fMaxV < v) fMaxV = v;
}
np++;
}
return np;
}
//-------------------------------------------
// Error of calculus
//
double CalcError(double *pfU, double *pfV, int nPoints,
double *pfFactors, int nFactors)
{
if (nPoints <= 0)
return 0.;
double fError = 0.;
for (int id=0; id < nPoints; id++ )
{
double u = pfU[id],
v = pfV[id],
v1= CalcInPoint(u, pfFactors, nFactors);
fError += (v1-v)*(v1-v);
}
fError = sqrt(fError/nPoints);
return fError;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Return the number of factors (see function 'Prepare')
// use to memory allocate for pfFactors
//
//extern "C" bool __declspec( dllexport ) __stdcall TransFromDisk(char *Base, char *Disk);
int __declspec(dllexport) __stdcall MaxOfFactors()
{
return N_FACTORS;
}
//
// Prepare approximation function V(U) = Function(U)
// V(U) = V0 + (U-U0)^M*(A0 + A1*U + ... +AN*U^N)
// Input:
// Array of points (U,V)
// fMinU, fMaxU - limits of U
// fMinV, fMaxV - limits of V
// pfU, pfV - array of nPoints points (U,V)
// pfW - weight of point
// nPoints - number of points in array
// Parameters:
// pfParams - array of parameters
// M = pfParams[0] - pow of
// N = pfParams[1] - pow of polinom approximation
// U0 = pfParams[2]
// V0 = pfParams[3]
// nParams - number of parameters in array
//
// Output:
// Array of factors is calculated.
// This factors will be used in function CalcInPoint(U, pfFactors)
// pfFactors - array of factors, defined by user
// Notes: pfFactors[*pnFactors-1] = Error of calculus
// nFactors:
// Input - maximum possible number of factors in array
//
// return: number of factors if success, else error code
//
int __declspec(dllexport) __stdcall Prepare (double fMinU, double fMaxU, double fMinV, double fMaxV,
double *pfU, double *pfV, double *pfW, int nPoints,
double *pfParams , int nParams ,
double *pfFactors, int nFactors)
{
int nResult = 0;
if (nPoints < 2) // not enough points
return -1;
if (nFactors < N_FACTORS) // not enough memory for result
return -2;
double fPoli = 1;
int nAppr = 4;
double fU0 = 0,
fV0 = 0;
if (nParams > 0) fPoli = pfParams[0];
if (nParams > 1) nAppr = (int)pfParams[1];
if (nParams > 2) fU0 = pfParams[2];
if (nParams > 3) fV0 = pfParams[3];
if (fPoli <-5) fPoli =-5; if (fPoli > 5) fPoli = 5;
if (nAppr < 0) nAppr = 0; if (nAppr > 5) nAppr = 5;
int nPointInAppr = FindLimits(fMinU, fMaxU, fMinV, fMaxV, pfU, pfV, nPoints, fU0);
double dU = fMaxU - fMinU;
if (dU < 0.) dU = -dU;
if (nPointInAppr < 5)
// nAppr = nPointInAppr;
nAppr = nPointInAppr-1;
int nn = nAppr + 2,
ns =(nAppr+1)*(nn+1);
// nAppr < 5
double fAppr[10];
double
*pfs,
*pfu;
// use: aa(i,j) == pfs[i*nn+j]
pfu = new double[nAppr+1+nPoints];//use as normed fU and coeff
pfs = new double[ns];
memset(pfs, 0, ns*sizeof(double));
int id, i, j;
int nSum = 0; // point with U>0, V>0
for (id=0; id < nPoints; id++ )
{
pfu[id] = pfU[id] / dU;
nSum++;
}
for (i=0; i <= nAppr; i++ )//equation coeffs
{
for (j=0; j <= nAppr+1; j++ ) aa(i,j) = 0.;
for (id=0; id < nPoints; id++ )
{
double u = pfU[id],
v;
if (u != fU0)
{
v = (pfV[id] - fV0) / pow(u-fU0, fPoli);
for (j=0; j <= nAppr; j++ )
aa(i, j) += (pfW[id] * PowInt(pfu[id], i+j));
aa(i, nAppr+1) += (pfW[id] * PowInt(pfu[id], i) * v);
}
}
}
CalcEquGauss(nAppr, pfs, pfu);
for (i=0; i<= nAppr; i++ )
{
fAppr[i] = pfu[i] / PowInt(dU, i);
}
nResult = N_FACTORS;
pfFactors[0] = nSum;
pfFactors[1] = fMinU; pfFactors[2] = fMaxU; // Unused now - reserved
pfFactors[3] = fMinV; pfFactors[4] = fMaxV; // Unused now - reserved
pfFactors[4] = 0; // Unused now - reserved
pfFactors[5] = fU0;
pfFactors[6] = fV0;
pfFactors[7] = fPoli;
pfFactors[8] = nAppr;
for (i=0; i<=nAppr; i++)
pfFactors[9+i] = fAppr[i];
pfFactors[N_FACTORS-1] = CalcError(pfU, pfV, nPoints, pfFactors, nFactors);
delete [] pfu;
delete [] pfs;
return nResult;
}
// Calculate value V = Function(fU)
// Input:
// fU
// pfFactors - array of factors, prepared in finction Prepare()
// pnFactors: - number of factors in array
//
// return: value calculated
//
double __declspec(dllexport) __stdcall CalcInPoint(double fU,
double *pfFactors, int nFactors)
{
if (nFactors < N_FACTORS)
return 0.;
double
U = fU,
U0 = pfFactors[5],
V0 = pfFactors[6],
fPoli = pfFactors[7];
int nAppr = (int)pfFactors[8];
if (fPoli <-5) fPoli =-5;
if (fPoli > 5) fPoli = 5;
if (nAppr < 0) return 0.;
double f = 1.,
fV= 0.;
for (int i=0; i<=nAppr; i++)
{
fV += f*pfFactors[9+i];
f *= U;
}
fV = V0 + fV * pow(U-U0, fPoli);
// fV = V0 + (U-U0)*(A0 + A1*U);
// fV = (A0 + A1*U + A2*U*U);
return fV;
}
// Fill information string with name of approximation method
// It is used in FindGraph <Master of approximations page 2><list of user defined functions>
// for example - "User's poli_n"
// Input:
// pstr - buffer TCHAR
// nMaxLength - maximum buffer length
//
// Output:
// pstr - name of approximation method
//
// return: string length if success, else -1
//
int __declspec(dllexport) __stdcall FunctionTitle(LPTSTR pstr, int nMaxLength)
{
if (pstr==0)
return -1;
lstrcpyn(pstr, TEXT(" y = V0 + (x-U0)^M *(A0 + A1*x...+AN*x^N)"), nMaxLength);
return lstrlen(pstr);
}
// Fill information string with name of approximation function
// for example - "V(U) = V0 + Exp(a*(U-U0))*Pow((U-U0), b)"
// It is used in FindGraph <Master of approximations page 3><Function description>
// Input:
// pstr - buffer TCHAR
// nMaxLength - maximum buffer length
//
// Output:
// pstr - name of approximation function
//
// return: string length if success, else -1
//
int __declspec(dllexport) __stdcall FunctionName(LPTSTR pstr, int nMaxLength)
{
if (pstr==0)
return -1;
lstrcpyn(pstr, TEXT("f(U) = V0 + (U-U0)^M *(A0+...+AN*U^N)"), nMaxLength);
return lstrlen(pstr);
}
// Fill information string with formula of calculated function f(U) = Formula()
// It is used in FindGraph <Master of approximations pages 4 and 5>
// Input:
// pstr - buffer TCHAR
// nMaxLength - maximum buffer length
// pfFactors - array of factors, prepared in finction Prepare()
// pnFactors: - number of factors in array
//
// Output:
// pstr - string of calculated function f(U)
//
// return: string length if success, else -1
//
int __declspec(dllexport) __stdcall FunctionString(double *pfFactors, int nFactors,
LPTSTR pstr, int nMaxLength)
{
if (pstr==0)
return -1;
if (nFactors < N_FACTORS)
return -2;
TCHAR sz[256];
double
U0 = pfFactors[5],
V0 = pfFactors[6],
fPoli= pfFactors[7],
fA[10];
int nAppr = (int)pfFactors[8];
if (nAppr>=0)
for (int i=0; i<=nAppr; i++)
{
fA[i] = pfFactors[9+i];
}
// sprintf(sz, TEXT("f(U) = %4.4g + (U-%4.4g)*(%4.4g + %4.4g*U + %4.4g*U2)"),V0, U0, A0, A1, A2);
// sprintf(sz, TEXT("f(U) = %4.4g + (U-%4.4g)*(%4.4g + %4.4g*U)"),V0, U0, A0, A1);
TCHAR sz1[24], sz2[24],
sza[256]; lstrcpy(sza, TEXT(""));
if (nAppr>=0)
for (int i=0; i<=nAppr; i++)
{
TCHAR szn[24];
sprintf(szn, TEXT("%4.4g"), fA[i]);
if (fA[i] > 0. && i)
lstrcat(sza, "+");
if (fA[i] != 0.)
{
lstrcat(sza, szn);
sprintf(szn, TEXT("*U^%1d"), i);
if (i)
lstrcat(sza, szn);
}
}
if (V0 != 0) sprintf(sz1, "%4.4g + ", V0);
else lstrcpy(sz1, TEXT(""));
if (U0 != 0) sprintf(sz2, "(U-%4.4g)", U0);
else lstrcpy(sz2, TEXT("U"));
if (fPoli==1) // default
sprintf(sz, TEXT("f(U) = %s%s * (%s)"),sz1, sz2, sza);
else
sprintf(sz, TEXT("f(U) = %s%s^%3.1f * (%s)"),sz1, sz2, fPoli, sza);
//TCHAR szz[64]; sprintf(szz,"\nM=%d N=%d",(int)fPoli, nAppr); lstrcat(sz, szz);
lstrcpyn(pstr, sz, nMaxLength);
return lstrlen(pstr);
}
// Fill information string with name of parameter and it's default value
// It is used in FindGraph <Master of approximations page 3>
// Input:
// nParam - number of edit box in page 3
// 1, 2, 3, 4
// see list of pfParams in function 'Prepare'
// pstr - buffer TCHAR
// nMaxLength - maximum buffer length
//
// Output:
// pstr - name of parameter[nParam]
// pfDefault - default value of parameter[nParam]
//
// return: string length if success, else -1
//
int __declspec(dllexport) __stdcall ParamInfo(int nParam, LPTSTR pstr, int nMaxLength, double *pfDefault)
{
if (pstr==0)
return -1;
switch (nParam)
{
case 1:
lstrcpyn(pstr, TEXT("M"), nMaxLength);
if (pfDefault != NULL)
*pfDefault = 1.;
break;
case 2:
lstrcpyn(pstr, TEXT("N"), nMaxLength);
if (pfDefault != NULL)
*pfDefault = 4.;
break;
case 3:
lstrcpyn(pstr, TEXT("U0"), nMaxLength);
if (pfDefault != NULL)
*pfDefault = 0.;
break;
case 4:
lstrcpyn(pstr, TEXT("V0"), nMaxLength);
if (pfDefault != NULL)
*pfDefault = 0.;
break;
default: return -1;
}
return lstrlen(pstr);
}